package com.cobo.common.core;

import com.alibaba.fastjson.JSONObject;
import lombok.extern.slf4j.Slf4j;
import org.apache.hc.client5.http.classic.methods.HttpDelete;
import org.apache.hc.client5.http.classic.methods.HttpGet;
import org.apache.hc.client5.http.classic.methods.HttpPost;
import org.apache.hc.client5.http.classic.methods.HttpPut;
import org.apache.hc.client5.http.impl.classic.CloseableHttpClient;
import org.apache.hc.client5.http.impl.classic.CloseableHttpResponse;
import org.apache.hc.client5.http.impl.classic.HttpClients;
import org.apache.hc.client5.http.ssl.NoopHostnameVerifier;
import org.apache.hc.core5.http.io.entity.EntityUtils;
import org.apache.hc.core5.http.io.entity.StringEntity;
import org.apache.hc.core5.net.URIBuilder;
import org.apache.hc.core5.ssl.SSLContextBuilder;
import org.apache.hc.core5.ssl.SSLContexts;
import org.apache.hc.core5.ssl.TrustStrategy;

import javax.net.ssl.SSLContext;
import java.io.IOException;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.util.Map;

@Slf4j
public class HttpUtils {

    public static final int HTTP_OK = 200;

    /**
     * 创建模拟客户端（针对 https 客户端禁用 SSL 验证）
     *
     * @return
     * @throws Exception
     */
    private static CloseableHttpClient createHttpClientWithNoSsl() throws Exception {
        // Create a trust manager that does not validate certificate chains
        SSLContext sslContext = null;
        try {
            SSLContextBuilder custom = SSLContexts.custom();
            custom.loadTrustMaterial(null, new TrustStrategy() {
                @Override
                public boolean isTrusted(X509Certificate[] x509Certificates, String s) throws CertificateException {
                    return true;
                }
            });
            sslContext = custom.build();
        } catch (Exception e) {
            log.error("HttpUtils class createHttpClientWithNoSsl method execute exception", e);
        }

//                LayeredConnectionSocketFactory sslSocketFactory = new SSLConnectionSocketFactory(ctx);
        return HttpClients.custom()
//                .setSSLContext(sslContext)
//                .setSSLHostnameVerifier(new NoopHostnameVerifier())
                .build();
    }

    public static String doGet(String url, Map<String, String> params, Map<String, String> headers) {
        CloseableHttpResponse res = null;
        CloseableHttpClient httpclient = null;
        String content = "";
        try {
            httpclient = createHttpClientWithNoSsl();
            URIBuilder uriBuilder = new URIBuilder(url);
            if (null != params) {
                for (Map.Entry<String, String> entry : params.entrySet()) {
                    uriBuilder.setParameter(entry.getKey(), entry.getValue());
                }
            }
            HttpGet httpGet = new HttpGet(uriBuilder.build());
            for (Map.Entry<String, String> entry : headers.entrySet()) {
                httpGet.setHeader(entry.getKey(), entry.getValue());
            }
            res = httpclient.execute(httpGet);

            if (res.getCode() == HTTP_OK) {
                content = EntityUtils.toString(res.getEntity());
            }
        } catch (Exception e) {
            log.error("", e);
        } finally {
            if (res != null) {
                log.info(res.getCode()+"");
                try {
                    res.close();
                } catch (IOException e) {
                }
            }
            if (httpclient != null) {
                try {
                    httpclient.close();
                } catch (IOException e) {
                }
            }
        }
        return content;
    }

    public static String doGet(String url, Map<String, String> params) {
        CloseableHttpResponse res = null;
        CloseableHttpClient httpclient = null;
        String content = "";
        try {
            httpclient = createHttpClientWithNoSsl();
            URIBuilder uriBuilder = new URIBuilder(url);
            if (null != params) {
                for (Map.Entry<String, String> entry : params.entrySet()) {
                    uriBuilder.setParameter(entry.getKey(), entry.getValue());
                }
            }
            HttpGet httpGet = new HttpGet(uriBuilder.build());
            res = httpclient.execute(httpGet);
            if (res.getCode() == HTTP_OK) {
                content = EntityUtils.toString(res.getEntity());
            }
        } catch (Exception e) {
            log.error("", e);
        } finally {
            if (res != null) {
                try {
                    res.close();
                } catch (IOException e) {
                }
            }
            if (httpclient != null) {
                try {
                    httpclient.close();
                } catch (IOException e) {
                }
            }
        }
        return content;
    }

    public static String doPost(String url, Object obj, Map<String, String> headers) {
        CloseableHttpClient httpClient = null;
        CloseableHttpResponse response = null;
        String resData = null;
        try {
            httpClient = createHttpClientWithNoSsl();
            HttpPost post = new HttpPost(url);
            post.setHeader("Content-Type", "application/json;charset=UTF-8");
            if (headers != null) {
                for (Map.Entry<String, String> entry : headers.entrySet()) {
                    post.setHeader(entry.getKey(), entry.getValue());
                }
            }
            if (obj == null) {
                obj = new JSONObject();
            }
            StringEntity stringEntity = new StringEntity(JSONObject.toJSONString(obj));
            post.setEntity(stringEntity);
            response = httpClient.execute(post);
            resData = EntityUtils.toString(response.getEntity());
        } catch (Exception e) {
            log.error("", e);
            if (response != null) {
                try {
                    response.close();
                } catch (IOException ioException) {
                }
            }
            if (httpClient != null) {
                try {
                    httpClient.close();
                } catch (IOException ioException) {
                }
            }
        }
        return resData;
    }

    public static String doPost(String url, Object obj) {
        CloseableHttpClient httpClient = null;
        CloseableHttpResponse response = null;
        String resData = null;
        try {
            httpClient = createHttpClientWithNoSsl();
            HttpPost post = new HttpPost(url);
            post.setHeader("Content-Type", "application/json;charset=UTF-8");
            StringEntity stringEntity = new StringEntity(JSONObject.toJSONString(obj));
            post.setEntity(stringEntity);
            response = httpClient.execute(post);
            resData = EntityUtils.toString(response.getEntity());
        } catch (Exception e) {
            log.error("", e);
            if (response != null) {
                try {
                    response.close();
                } catch (IOException ioException) {
                }
            }
            if (httpClient != null) {
                try {
                    httpClient.close();
                } catch (IOException ioException) {
                }
            }
        }
        return resData;
    }

    public static String doDelete(String url, Map<String, String> params, Map<String, String> headers) {
        CloseableHttpResponse res = null;
        CloseableHttpClient httpclient = null;
        String content = "";
        try {
            httpclient = createHttpClientWithNoSsl();
            URIBuilder uriBuilder = new URIBuilder(url);
            if (null != params) {
                for (Map.Entry<String, String> entry : params.entrySet()) {
                    uriBuilder.setParameter(entry.getKey(), entry.getValue());
                }
            }
            HttpDelete httpDelete = new HttpDelete(uriBuilder.build());
            for (Map.Entry<String, String> entry : headers.entrySet()) {
                httpDelete.setHeader(entry.getKey(), entry.getValue());
            }
            res = httpclient.execute(httpDelete);
            if (res.getCode() == HTTP_OK) {
                content = EntityUtils.toString(res.getEntity());
            }
        } catch (Exception e) {
            log.error("", e);
        } finally {
            if (res != null) {
                log.info(res.getCode() + "");
                try {
                    res.close();
                } catch (IOException e) {
                }
            }
            if (httpclient != null) {
                try {
                    httpclient.close();
                } catch (IOException e) {
                }
            }
        }
        return content;
    }

}
